package ajaxjs.net;

import java.lang.management.ManagementFactory;
import java.net.InetAddress; 
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.ReflectionException;
import javax.servlet.http.HttpServletRequest;

/** 
 * 获取服务端或客户端 IP
 * ************************************************ 
 * 知识的补充 
 * InetAddress 有两个子类：Inet4Address 和 Inet6Address 此类表示互联网协议 (IP) 地址。  
 * IP 地址是 IP 使用的 32 位或 128 位无符号数字， 它是一种低级协议，UDP 和 TCP 协议都是在它的基础上构建的。 
 * ************************************************ 
 * 主机名就是计算机的名字（计算机名），网上邻居就是根据主机名来识别的。这个名字可以随时更改，从我的电脑属性的计算机名就可更改。 
 * 用户登陆时候用的是操作系统的个人用户帐号，这个也可以更改， 从控制面板的用户界面里改就可以了。这个用户名和计算机名无关。 
 */ 
public class Ip {
    public static void main(String[] args) { 
		System.out.println("本机IP：" + getLocalHostIP()); 
		System.out.println("本地主机名字为：" + getLocalHostName()); 
		System.out.println(getReal_LAN_IP());

		String[] localIP = getAllLocalHostIP(); 
		for (int i = 0; i < localIP.length; i++) { 
		    System.out.println(localIP[i]); 
		} 
        
//		InetAddress baidu = InetAddress.getByName("www.baidu.com");
//		System.out.println("baidu : " + baidu);
//		System.out.println("baidu IP: " + baidu.getHostAddress());
//		System.out.println("baidu HostName: " + baidu.getHostName());
    } 	
	
    /**
     * 返回本地主机
     * @return
     */
	private static InetAddress getLocalhost(){
		InetAddress addr = null;
		
		try {
			addr = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			System.out.println("返回本地主机失败！");
			e.printStackTrace();
		} 
		
		return addr;
	}

	/** 
     * 获取本机的IP 
     * 返回 IP 地址字符串（以文本表现形式）
     * @return
     */ 
	public static String getLocalHostIP() {	
		return getLocalhost().getHostAddress(); 
	} 
       
     /** 
      * 或者主机名： 
      * @return 
      */ 
     public static String getLocalHostName() { 
          return getLocalhost().getHostName();
     } 
   
	/**
	 * 获得本地所有的IP地址
	 * @return
	 */
	public static String[] getAllLocalHostIP() {
		String hostName = getLocalHostName();// 获得主机名

		InetAddress[] addrs = null;
		try {
			addrs = InetAddress.getAllByName(hostName); // 在给定主机名的情况下，根据系统上配置的名称服务返回其 IP 地址所组成的数组。
		} catch (UnknownHostException e) {
			System.out.println("未知主机");
			e.printStackTrace();
			
			return null;
		}
		
		String[] ret = null;
		if (addrs.length > 0) {
			ret = new String[addrs.length];
			for (int i = 0; i < addrs.length; i++) 
				ret[i] = addrs[i].getHostAddress(); // getHostAddress() 返回 IP 地址字符串（以文本表现形式）
		}
		
		return ret;
	}
     
     /**
      * 以 192.168.1.x 开头的都是局域网内的 ip
      * @return
      */
     public static String getReal_LAN_IP(){
    	 String ip = null;
         String[] localIP = getAllLocalHostIP(); 
         
         for (int i = 0; i < localIP.length; i++) { 
        	 if(localIP[i].startsWith("192.168.1") || localIP[i].startsWith("192.168.0")){
        		 return localIP[i];
        	 }
         } 
         
    	 return ip;
     }
	     
 	/**
 	 * 获取请求的 ip 地址
 	 * @param request
 	 * @return
 	 */
 	public static String getClientIP(HttpServletRequest request) {    
 	    String s = request.getHeader("X-Forwarded-For");
 	    
 	    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s))
 	        s = request.getHeader("Proxy-Client-IP");
 	    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s))
 	        s = request.getHeader("WL-Proxy-Client-IP");
 	    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s))
 	        s = request.getHeader("HTTP_CLIENT_IP");
 	    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s))
 	        s = request.getHeader("HTTP_X_FORWARDED_FOR");
 	    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s))
 	        s = request.getRemoteAddr();
 	    
 	    if ("127.0.0.1".equals(s) || "0:0:0:0:0:0:0:1".equals(s))
 	    	s = getLocalHostIP();
 	    
 	    return s;
 	}	
 	
 	/**
	 * 加入一个是否 调试模式 的逻辑
	 * @return
	 * @throws MalformedObjectNameException
	 * @throws NullPointerException
	 * @throws UnknownHostException
	 * @throws AttributeNotFoundException
	 * @throws InstanceNotFoundException
	 * @throws MBeanException
	 * @throws ReflectionException
	 */
	public static List<String> getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException,
		AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
		
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
		String hostname;
		try{
			hostname = InetAddress.getLocalHost().getHostName();
		}catch(Exception e){
			// linux 统统都是正式环境
			// 要真正解决的话，在host文件中加入 127.0.0.1 localhost，麻烦！ 
			  // 如果发现 异常，那么表示是 正式环境
			return null;
		}
		InetAddress[] addresses = InetAddress.getAllByName(hostname);
		ArrayList<String> endPoints = new ArrayList<String>();
		
		for (Iterator<ObjectName> i = objs.iterator(); i.hasNext();) {
			ObjectName obj = i.next();
			String scheme = mbs.getAttribute(obj, "scheme").toString();
			String port = obj.getKeyProperty("port");
			
			//if("80".equals(port))isDebug = false; // 如果发现 tomcata 有提供 80 端口，那么表示是 正式环境
			
			for (InetAddress addr : addresses) {
				String host = addr.getHostAddress();
				String ep = scheme + "://" + host + ":" + port;
				endPoints.add(ep);
			}
		}
		
		return endPoints;
	}
}